1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import java.awt.*;
34 import java.awt.event.*;
35 import java.awt.geom.*;
36 import java.awt.image.*;
37
38 public class PolyVertTest {
39 static int TESTWIDTH;
40 static int TESTHEIGHT;
41 static final int REG_TEST_WIDTH = 10;
42 static final int REG_TEST_HEIGHT = 10;
43 static final int FULL_TEST_WIDTH = 50;
44 static final int FULL_TEST_HEIGHT = 200;
45
46 static final int FRINGE = 2;
47 static final int GREEN = Color.green.getRGB();
48 static final int RED = Color.red.getRGB();
49
50 static BufferedImage refImg;
51 static BufferedImage errorImg;
52 static Graphics errorG;
53 static Component testCanvas;
54
55 static int totalbadpixels;
56 static int totalfuzzypixels;
57 static int numbadtests;
58 static int numfuzzytests;
59 static int numframes;
60 static int fuzzystarty;
61
62 static boolean counting;
63 static boolean showerrors;
64 static boolean showresults;
65 static boolean fringe;
66 static boolean forceerror;
67 static boolean fulltest = true;
68 static boolean hwonly;
69
70 static WindowListener windowCloser = new WindowAdapter() {
71 public void windowClosing(WindowEvent e) {
72 e.getWindow().hide();
73 if (--numframes <= 0) {
74 System.exit(0);
75 }
76 }
77 };
78
79 public PolyVertTest() {
80
81
82
83
84 }
85
86 static int polypts[][][] = {
87 {
88
89 {}, {},
90 },
91 {
92
93 { 0 }, { 0 },
94 },
95 {
96
97 { 0, 5 }, { 0, 0 },
98 { 0, 0, 6, 1,
99 10, 0, 6, 1,
100 20, 0, 6, 1 },
101 { 0, 0, 6, 1,
102 10, 0, 1, 1, 15, 0, 1, 1,
103 20, 0, 1, 1, 25, 0, 1, 1 },
104 { 10, 0, 1, 1,
105 20, 0, 1, 1 },
106 },
107 {
108
109 { 0, 5, 5 }, { 0, 0, 5 },
110
111 { 0, 0, 6, 1, 5, 1, 1, 5,
112
113 10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
114 12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
115
116 20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
117 22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
118
119 { 0, 0, 6, 1, 5, 1, 1, 5,
120
121 10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
122 12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
123
124 20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
125 22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
126
127 { 10, 0, 1, 1,
128 20, 0, 1, 1 },
129 },
130 {
131
132 { 0, 5, 5, 0 }, { 0, 0, 5, 0 },
133
134 { 0, 0, 6, 1, 5, 1, 1, 5, 1, 1, 1, 1,
135 2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1, 1,
136
137 10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
138 12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
139
140 20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
141 22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
142
143 { 1, 0, 5, 1, 5, 1, 1, 5, 1, 1, 1, 1,
144 2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1, 1,
145
146 10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
147 12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
148
149 20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
150 22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
151
152 { 0, 0, 1, 1,
153 10, 0, 1, 1,
154 20, 0, 1, 1 },
155 },
156 {
157
158 { 0, 0 }, { 0, 0 },
159 { 0, 0, 1, 1,
160 10, 0, 1, 1,
161 20, 0, 1, 1 },
162 },
163 {
164
165 { 0, 0, 0 }, { 0, 0, 0 },
166 { 0, 0, 1, 1,
167 10, 0, 1, 1,
168 20, 0, 1, 1 },
169 },
170 };
171
172 public static void render(Graphics2D g2d) {
173 g2d.setColor(Color.white);
174 g2d.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
175 g2d.setColor(Color.black);
176
177 if (forceerror) {
178 g2d.fillRect(2, 2, 2, 2);
179 g2d.fillRect(15, 5, 1, 1);
180 }
181
182 if (!fulltest) {
183 g2d.draw(new Rectangle2D.Double(5, 5, 0, 0));
184 return;
185 }
186
187 g2d.drawLine(10, 10, 10, 10);
188 g2d.draw(new Line2D.Double(20, 10, 20, 10));
189
190 g2d.drawRect(10, 20, 0, 0);
191 g2d.draw(new Rectangle2D.Double(20, 20, 0, 0));
192
193 g2d.setXORMode(Color.white);
194
195 g2d.drawLine(10, 30, 10, 30);
196 g2d.draw(new Line2D.Double(20, 30, 20, 30));
197
198 g2d.drawRect(10, 40, 0, 0);
199 g2d.draw(new Rectangle2D.Double(20, 40, 0, 0));
200
201 g2d.setPaintMode();
202
203 int y = 50;
204 for (int i = 0; i < polypts.length; i++) {
205 int data[][] = polypts[i];
206 int xpoints[] = data[0];
207 int ypoints[] = data[1];
208 int npoints = xpoints.length;
209 g2d.translate(10, y);
210 g2d.drawPolyline(xpoints, ypoints, npoints);
211 g2d.translate(10, 0);
212 g2d.drawPolygon(xpoints, ypoints, npoints);
213 g2d.translate(10, 0);
214 g2d.draw(new Polygon(xpoints, ypoints, npoints));
215 g2d.translate(-30, -y);
216 y += 10;
217 }
218 g2d.setXORMode(Color.white);
219 for (int i = 0; i < polypts.length; i++) {
220 int data[][] = polypts[i];
221 int xpoints[] = data[0];
222 int ypoints[] = data[1];
223 int npoints = xpoints.length;
224 g2d.translate(10, y);
225 g2d.drawPolyline(xpoints, ypoints, npoints);
226 g2d.translate(10, 0);
227 g2d.drawPolygon(xpoints, ypoints, npoints);
228 g2d.translate(10, 0);
229 g2d.draw(new Polygon(xpoints, ypoints, npoints));
230 g2d.translate(-30, -y);
231 y += 10;
232 }
233 g2d.setPaintMode();
234 }
235
236 public Dimension getPreferredSize() {
237 return new Dimension(500, 500);
238 }
239
240 public static void usage(int exitcode) {
241 System.err.println("usage: java PolyVertTest [<option>]*");
242 System.err.println(" -usage "+
243 "print this usage summary");
244 System.err.println(" -count "+
245 "run all tests and accumulate error counts");
246 System.err.println(" -forceerror "+
247 "force at least one error in each test");
248 System.err.println(" -fringe "+
249 "draw a yellow fringe around problems");
250 System.err.println(" -showerrors "+
251 "display results window for tests with problems");
252 System.err.println(" -showresults "+
253 "display results window for all tests");
254 System.err.println(" -quicktest "+
255 "only run test cases reported in bug reports");
256 System.err.println(" -fulltest "+
257 "run full suite of test cases for a 'unit test'");
258 System.err.println(" -hwonly "+
259 "only run tests for screen and VolatileImage");
260 System.exit(exitcode);
261 }
262
263 public static void main(String argv[]) {
264 for (int i = 0; i < argv.length; i++) {
265 String arg = argv[i];
266 if (arg.equalsIgnoreCase("-count")) {
267 counting = true;
268 } else if (arg.equalsIgnoreCase("-forceerror")) {
269 forceerror = true;
270 } else if (arg.equalsIgnoreCase("-fringe")) {
271 fringe = true;
272 } else if (arg.equalsIgnoreCase("-showerrors")) {
273 showerrors = true;
274 } else if (arg.equalsIgnoreCase("-showresults")) {
275 showresults = true;
276 } else if (arg.equalsIgnoreCase("-quicktest")) {
277 fulltest = false;
278 } else if (arg.equalsIgnoreCase("-fulltest")) {
279 fulltest = true;
280 } else if (arg.equalsIgnoreCase("-hwonly")) {
281 hwonly = true;
282 } else if (arg.equalsIgnoreCase("-usage")) {
283 usage(0);
284 } else {
285 System.err.println("unknown option: "+arg);
286 usage(1);
287 }
288 }
289
290 if (fulltest) {
291 TESTWIDTH = FULL_TEST_WIDTH;
292 TESTHEIGHT = FULL_TEST_HEIGHT;
293 } else {
294 TESTWIDTH = REG_TEST_WIDTH;
295 TESTHEIGHT = REG_TEST_HEIGHT;
296 }
297
298
299
300
301 numframes++;
302
303 makeReferenceImage();
304 testScreen();
305 testVolatileImage();
306 if (!hwonly) {
307 testBufferedImage();
308 testOffscreen();
309 testCompatibleImages();
310 }
311 if (totalfuzzypixels > 0) {
312 System.err.println(totalfuzzypixels+" fuzzy pixels found in "+
313 numfuzzytests+" tests");
314 }
315 if (totalbadpixels > 0) {
316 throw new RuntimeException(totalbadpixels+" bad pixels found in "+
317 numbadtests+" tests");
318 }
319 System.out.println("Test done - no bad pixels found");
320
321 --numframes;
322
323 if (counting || ((showresults || showerrors) && numframes == 0)) {
324 System.exit(0);
325 }
326 }
327
328 public static void makeReferenceImage() {
329 refImg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
330 BufferedImage.TYPE_INT_RGB);
331 Graphics g = refImg.getGraphics();
332
333 g.setColor(Color.white);
334 g.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
335
336 g.setColor(Color.black);
337
338 if (!fulltest) {
339 g.fillRect(5, 5, 1, 1);
340 g.dispose();
341 return;
342 }
343
344 for (int y = 10; y < 50; y += 10) {
345 g.fillRect(10, y, 1, 1);
346 g.fillRect(20, y, 1, 1);
347 }
348 int y = 50;
349 for (int i = 0; i < polypts.length; i++) {
350 int data[][] = polypts[i];
351 g.translate(10, y);
352 if (data.length > 2) {
353 int rectvals[] = data[2];
354 for (int j = 0; j < rectvals.length; j += 4) {
355 g.fillRect(rectvals[j+0], rectvals[j+1],
356 rectvals[j+2], rectvals[j+3]);
357 }
358 }
359 g.translate(-10, -y);
360 y += 10;
361 }
362 fuzzystarty = y;
363 for (int i = 0; i < polypts.length; i++) {
364 int data[][] = polypts[i];
365 g.translate(10, y);
366 if (data.length > 2) {
367 int rectvals[] = data.length > 3 ? data[3] : data[2];
368 for (int j = 0; j < rectvals.length; j += 4) {
369 g.fillRect(rectvals[j+0], rectvals[j+1],
370 rectvals[j+2], rectvals[j+3]);
371 }
372 }
373 g.translate(-10, -y);
374 y += 10;
375 }
376 g.dispose();
377 }
378
379 public static void initerrorbuf() {
380 if (errorImg == null) {
381 droperrorbuf();
382 errorImg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
383 BufferedImage.TYPE_INT_RGB);
384 }
385 if (errorG == null) {
386 errorG = errorImg.getGraphics();
387 }
388 errorG.setColor(Color.green);
389 errorG.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
390 errorG.setColor(Color.red);
391 }
392
393 public static void droperrorbuf() {
394 errorImg = null;
395 if (errorG != null) {
396 errorG.dispose();
397 }
398 errorG = null;
399 }
400
401 public static void test(Image img, String name) {
402 Graphics2D g2d = (Graphics2D) img.getGraphics();
403 render(g2d);
404 g2d.dispose();
405 verify(img, name);
406 }
407
408 public static void test(BufferedImage bimg, String name) {
409 Graphics2D g2d = bimg.createGraphics();
410 render(g2d);
411 g2d.dispose();
412 verify(bimg, name);
413 }
414
415 public static void verify(Image img, String name) {
416 BufferedImage bimg;
417 if (img instanceof BufferedImage) {
418 bimg = (BufferedImage) img;
419 } else {
420 bimg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
421 BufferedImage.TYPE_INT_RGB);
422 Graphics g = bimg.getGraphics();
423 g.drawImage(img, 0, 0, null);
424 g.dispose();
425 }
426 verify(bimg, name);
427 }
428
429 public static boolean isFuzzyPixel(int X, int Y) {
430 int ytrans = fuzzystarty;
431 if (!fulltest || Y < ytrans) {
432 return false;
433 }
434 for (int i = 0; i < polypts.length; i++) {
435 int data[][] = polypts[i];
436 if (data.length > 4) {
437 int rectvals[] = data[4];
438 for (int j = 0; j < rectvals.length; j += 4) {
439 int rectx = rectvals[j+0] + 10;
440 int recty = rectvals[j+1] + ytrans;
441 int rectw = rectvals[j+2];
442 int recth = rectvals[j+3];
443 if (X >= rectx && Y >= recty &&
444 X < rectx + rectw && Y < recty + recth)
445 {
446 return true;
447 }
448 }
449 }
450 ytrans += 10;
451 }
452 return false;
453 }
454
455 public static void verify(BufferedImage bimg, String name) {
456 int numbadpixels = 0;
457 int numfuzzypixels = 0;
458 for (int y = 0; y < TESTHEIGHT; y++) {
459 for (int x = 0; x < TESTWIDTH; x++) {
460 if (refImg.getRGB(x, y) != bimg.getRGB(x, y)) {
461 boolean isfuzzy = isFuzzyPixel(x, y);
462 if (showerrors || showresults) {
463 if (errorG == null) {
464 initerrorbuf();
465 }
466 errorG.setColor(isfuzzy ? Color.blue : Color.red);
467 errorG.fillRect(x, y, 1, 1);
468 } else if (!counting && !isfuzzy) {
469 throw new RuntimeException("Error at "+x+", "+y+
470 " while testing: "+name);
471 }
472 if (isfuzzy) {
473 numfuzzypixels++;
474 } else {
475 numbadpixels++;
476 }
477 }
478 }
479 }
480 if (numbadpixels > 0 || numfuzzypixels > 0) {
481 if (numbadpixels > 0) {
482 totalbadpixels += numbadpixels;
483 numbadtests++;
484 }
485 if (numfuzzypixels > 0) {
486 totalfuzzypixels += numfuzzypixels;
487 numfuzzytests++;
488 }
489 System.out.println(numbadpixels+" bad pixels and "+
490 numfuzzypixels+" questionable pixels "+
491 "found while testing "+name);
492 if (showerrors || showresults) {
493 displaydiffs(bimg, name);
494 }
495 } else if (showresults) {
496 if (errorG == null) {
497 initerrorbuf();
498 }
499 displaydiffs(bimg, name);
500 }
501 }
502
503 public static void displaydiffs(BufferedImage bimg, String name) {
504 if (fringe) {
505 errorG.setColor(Color.yellow);
506 for (int y = 0; y < TESTHEIGHT; y++) {
507 for (int x = 0; x < TESTWIDTH; x++) {
508 if (errorImg.getRGB(x, y) == RED) {
509 for (int iy = y-FRINGE; iy <= y+FRINGE; iy++) {
510 for (int ix = x-FRINGE; ix <= x+FRINGE; ix++) {
511 if (ix >= 0 && ix < TESTWIDTH &&
512 iy >= 0 && iy < TESTHEIGHT &&
513 errorImg.getRGB(ix, iy) == GREEN)
514 {
515 errorG.fillRect(ix, iy, 1, 1);
516 }
517 }
518 }
519 }
520 }
521 }
522 }
523 Frame f = new Frame("Results for "+name);
524 f.setLayout(new BorderLayout());
525 f.addWindowListener(windowCloser);
526 ++numframes;
527 Panel p = new Panel();
528 p.add(new ImageCanvas(bimg));
529 p.add(new ImageCanvas(errorImg));
530 p.add(new ImageCanvas(refImg));
531 f.add(p, "Center");
532 droperrorbuf();
533 f.pack();
534 f.show();
535 }
536
537 public static void testBufferedImage() {
538 testBufferedImage(BufferedImage.TYPE_INT_RGB, "IntXrgb");
539 testBufferedImage(BufferedImage.TYPE_INT_ARGB, "IntArgb");
540 testBufferedImage(BufferedImage.TYPE_3BYTE_BGR, "ThreeByte");
541 testBufferedImage(BufferedImage.TYPE_4BYTE_ABGR, "FourByte");
542 testBufferedImage(BufferedImage.TYPE_USHORT_555_RGB, "UShort555");
543 testBufferedImage(BufferedImage.TYPE_BYTE_GRAY, "ByteGray");
544 testBufferedImage(BufferedImage.TYPE_BYTE_INDEXED, "Indexed");
545 }
546
547 public static void testBufferedImage(int type, String name) {
548 BufferedImage bimg = new BufferedImage(TESTWIDTH, TESTHEIGHT, type);
549 test(bimg, name);
550 }
551
552 public static void testScreen() {
553 Frame f = new Frame("PolyVertTest");
554 TestCanvas child = new TestCanvas();
555 testCanvas = child;
556 f.add(child);
557 f.pack();
558 f.show();
559 BufferedImage bimg = child.getImage();
560 f.hide();
561 verify(bimg, "Screen");
562 }
563
564 public static void testOffscreen() {
565 Image img = testCanvas.createImage(TESTWIDTH, TESTHEIGHT);
566 test(img, "Offscreen");
567 }
568
569 public static void testCompatibleImages() {
570 GraphicsEnvironment genv =
571 GraphicsEnvironment.getLocalGraphicsEnvironment();
572 GraphicsDevice gdevs[] = genv.getScreenDevices();
573 for (int i = 0; i < gdevs.length; i++) {
574 testCompatibleImages(gdevs[i]);
575 }
576 }
577
578 public static void testCompatibleImages(GraphicsDevice gdev) {
579 GraphicsConfiguration gconfigs[] = gdev.getConfigurations();
580 for (int i = 0; i < gconfigs.length; i++) {
581 testCompatibleImages(gconfigs[i]);
582 }
583 }
584
585 public static void testCompatibleImages(GraphicsConfiguration gconfig) {
586 test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT),
587 gconfig+".createCompat()");
588 test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
589 Transparency.OPAQUE),
590 gconfig+".createCompat(OPAQUE)");
591 test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
592 Transparency.BITMASK),
593 gconfig+".createCompat(BITMASK)");
594 test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
595 Transparency.TRANSLUCENT),
596 gconfig+".createCompat(TRANSLUCENT)");
597 test(gconfig.createCompatibleVolatileImage(TESTWIDTH, TESTHEIGHT),
598 gconfig+".createCompatVolatile()");
599 }
600
601 public static void testVolatileImage() {
602 Image img = testCanvas.createVolatileImage(TESTWIDTH, TESTHEIGHT);
603 test(img, "Volatile");
604 }
605
606 public static class ImageCanvas extends Canvas {
607 BufferedImage bimg;
608
609 public ImageCanvas(BufferedImage bimg) {
610 this.bimg = bimg;
611 }
612
613 public Dimension getPreferredSize() {
614 return new Dimension(bimg.getWidth(), bimg.getHeight());
615 }
616
617 public void paint(Graphics g) {
618 g.drawImage(bimg, 0, 0, null);
619 }
620 }
621
622 public static class TestCanvas extends Canvas {
623 BufferedImage bimg;
624
625 public Dimension getPreferredSize() {
626 return new Dimension(TESTWIDTH, TESTHEIGHT);
627 }
628
629 public void paint(Graphics g) {
630 if (bimg != null ||
631 getWidth() < TESTWIDTH ||
632 getHeight() < TESTHEIGHT)
633 {
634 return;
635 }
636 render((Graphics2D) g);
637 Toolkit.getDefaultToolkit().sync();
638 Point p = getLocationOnScreen();
639 Rectangle r = new Rectangle(p.x, p.y, TESTWIDTH, TESTHEIGHT);
640 try {
641 bimg = new Robot().createScreenCapture(r);
642 } catch (AWTException e) {
643 e.printStackTrace();
644 }
645 synchronized (this) {
646 notifyAll();
647 }
648 }
649
650 public synchronized BufferedImage getImage() {
651 while (bimg == null) {
652 try {
653 wait();
654 } catch (InterruptedException e) {
655 return null;
656 }
657 }
658 return bimg;
659 }
660 }
661 }